#ifndef DBMANAGER_H
#define DBMANAGER_H

#include <QObject>
#include <QSqlDatabase>
#include <QSqlQuery>
#include <QSqlError>
#include <QMutex>
#include <QDateTime>
#include <QVector>
#include "../core/meter.h"

/**
 * @brief 历史数据结构
 */
struct HistoryData
{
    int meterId;         ///< 电表ID
    double ua;           ///< A相电压(V)
    double ub;           ///< B相电压(V)
    double uc;           ///< C相电压(V)
    double ia;           ///< A相电流(A)
    double ib;           ///< B相电流(A)
    double ic;           ///< C相电流(A)
    QDateTime timestamp; ///< 时间戳
};

/**
 * @brief 报警记录结构
 */
struct AlarmRecord
{
    int id;              ///< 报警ID（自增）
    int meterId;         ///< 电表ID
    QString alarmType;   ///< 报警类型（电压跌落、过流等）
    double alarmValue;   ///< 报警值
    double threshold;    ///< 阈值
    QDateTime timestamp; ///< 报警时间
    bool acknowledged;   ///< 是否已确认
    QDateTime ackTime;   ///< 确认时间
};

/**
 * @brief 电表信息结构
 */
struct MeterInfo
{
    int meterId;          ///< 电表ID
    QString name;         ///< 电表名称
    QString location;     ///< 位置
    int busId;            ///< 总线ID
    bool enabled;         ///< 是否启用
    QDateTime createTime; ///< 创建时间
    QDateTime updateTime; ///< 更新时间
};

/**
 * @brief 数据库管理器类（单例模式）
 *
 * 功能：
 * - SQLite 数据库操作封装
 * - 历史数据批量写入（每5分钟）
 * - 报警记录管理
 * - 电表配置管理
 * - 查询优化（索引、分页）
 * - 线程安全
 */
class DBManager : public QObject
{
    Q_OBJECT

public:
    /**
     * @brief 获取数据库管理器单例
     */
    static DBManager *instance();

    /**
     * @brief 初始化数据库
     * @param dbPath 数据库文件路径，如果为空则使用默认路径
     *               默认路径: C:/Users/86188/Desktop/ModbusPro/QModbusPowerCloud/data/powercloud.db
     * @return 是否初始化成功
     */
    bool initialize(const QString &dbPath = "");

    /**
     * @brief 关闭数据库连接
     */
    void close();

    /**
     * @brief 检查数据库是否已连接
     */
    bool isConnected() const;

    // ============ 电表管理 ============

    /**
     * @brief 保存电表信息
     * @param info 电表信息
     * @return 是否成功
     */
    bool saveMeterInfo(const MeterInfo &info);

    /**
     * @brief 获取所有电表信息
     * @return 电表信息列表
     */
    QVector<MeterInfo> getAllMeterInfo();

    // ============ 历史数据管理 ============

    /**
     * @brief 插入单条历史数据
     * @param data 历史数据
     * @return 是否成功
     */
    bool insertHistoryData(const HistoryData &data);

    /**
     * @brief 批量插入历史数据
     * @param dataList 历史数据列表
     * @return 成功插入的数量
     */
    int batchInsertHistoryData(const QVector<HistoryData> &dataList);

    /**
     * @brief 查询历史数据
     * @param meterId 电表ID（-1表示所有电表）
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @return 历史数据列表
     */
    QVector<HistoryData> queryHistoryData(int meterId,
                                          const QDateTime &startTime,
                                          const QDateTime &endTime);

    /**
     * @brief 查询历史数据（分页）
     * @param meterId 电表ID
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @param offset 偏移量
     * @param limit 每页数量
     * @return 历史数据列表
     */
    QVector<HistoryData> queryHistoryDataPaged(int meterId,
                                               const QDateTime &startTime,
                                               const QDateTime &endTime,
                                               int offset,
                                               int limit);

    /**
     * @brief 获取历史数据数量
     * @param meterId 电表ID（-1表示所有电表）
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @return 记录数量
     */
    int getHistoryDataCount(int meterId,
                            const QDateTime &startTime,
                            const QDateTime &endTime);

    /**
     * @brief 删除指定时间段的历史数据
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @return 删除的记录数
     */
    int deleteHistoryData(const QDateTime &startTime, const QDateTime &endTime);

    // ============ 报警记录管理 ============

    /**
     * @brief 插入报警记录
     * @param record 报警记录
     * @return 插入的记录ID，失败返回-1
     */
    int insertAlarmRecord(const AlarmRecord &record);

    /**
     * @brief 查询报警记录
     * @param meterId 电表ID（-1表示所有电表）
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @param acknowledged 是否已确认（-1表示全部）
     * @return 报警记录列表
     */
    QVector<AlarmRecord> queryAlarmRecords(int meterId,
                                           const QDateTime &startTime,
                                           const QDateTime &endTime,
                                           int acknowledged = -1);

    /**
     * @brief 确认报警
     * @param alarmId 报警ID
     * @return 是否成功
     */
    bool acknowledgeAlarm(int alarmId);

    /**
     * @brief 批量确认报警
     * @param alarmIds 报警ID列表
     * @return 成功确认的数量
     */
    int batchAcknowledgeAlarms(const QVector<int> &alarmIds);

    /**
     * @brief 删除报警记录
     * @param alarmId 报警ID
     * @return 是否成功
     */
    bool deleteAlarmRecord(int alarmId);

    /**
     * @brief 获取未确认报警数量
     * @return 未确认报警数量
     */
    int getUnacknowledgedAlarmCount();

    // ============ 数据库维护 ============

    /**
     * @brief 清理旧数据
     * @param days 保留最近N天的数据
     * @return 删除的记录数
     */
    int cleanOldData(int days);

    /**
     * @brief 优化数据库（VACUUM）
     * @return 是否成功
     */
    bool optimizeDatabase();

    /**
     * @brief 获取数据库大小（字节）
     */
    qint64 getDatabaseSize() const;

    /**
     * @brief 获取表记录数
     * @param tableName 表名
     * @return 记录数
     */
    int getTableRowCount(const QString &tableName);

signals:
    /**
     * @brief 数据库错误信号
     */
    void databaseError(const QString &error);

    /**
     * @brief 历史数据插入信号
     */
    void historyDataInserted(int count);

    /**
     * @brief 报警记录插入信号
     */
    void alarmRecordInserted(int alarmId);

private:
    explicit DBManager(QObject *parent = nullptr);
    ~DBManager();

    DBManager(const DBManager &) = delete;
    DBManager &operator=(const DBManager &) = delete;

    /**
     * @brief 创建数据库表结构
     */
    bool createTables();

    /**
     * @brief 执行SQL语句
     * @param sql SQL语句
     * @param bindValues 绑定值列表
     * @return 是否成功
     */
    bool executeSQL(const QString &sql, const QVariantList &bindValues = QVariantList());

    /**
     * @brief 记录数据库错误
     */
    void logDatabaseError(const QString &context, const QSqlError &error);

private:
    static DBManager *m_instance; ///< 单例实例
    static QMutex m_mutex;        ///< 互斥锁

    QSqlDatabase m_database; ///< 数据库连接
    QString m_dbPath;        ///< 数据库路径
    bool m_connected;        ///< 是否已连接
};

#endif // DBMANAGER_H
